home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / batchut / pshdir1a.zip / PUSHDIR.ASM < prev    next >
Assembly Source File  |  1988-12-22  |  8KB  |  249 lines

  1. main    group    code
  2. code    segment    public    para    'code'
  3. assume    cs:main
  4.  
  5. org    100h                ;.COM file
  6.  
  7. BEGIN:    jmp    START            ;program starts here
  8. ;        db    "Copyright 1986 Ziff-Davis Publishing Co.",1Ah
  9. ;            Changes made on 12/22/88 by Mike Williams
  10. ;            1. Support command line parm to also CHDIR
  11. ;            2. If path string refers to a drive, log that drive
  12. ;
  13. signature    db    'PUSHDIR VERSION 1.a'
  14. lengthsignature = $ - signature
  15.  
  16. savedint16    dd    ?        ;old int 16h vector
  17.  
  18. nextpush    dw    offset main:push1dir    ;next place to save a dir
  19. push1dir    db    67 dup (0)        ;storage for a saved dir
  20. push2dir    db    67 dup (0)        ;more storage
  21. push3dir    db    67 dup (0)        ;more storage
  22. push4dir    db    67 dup (0)        ;more storage
  23. push5dir    db    67 dup (0)        ;more storage
  24. push6dir    db    67 dup (0)        ;last storage
  25.  
  26. ;up to here must be EXACTLY identical in both PUSHDIR and POPDIR so that
  27. ;popdir can know how to access the memory space reserved by the first
  28. ;pushdir.
  29.  
  30. ;myint16 is an interrupt handler chained onto the existing interrupt handler.
  31. ;it is used to find out if PUSHDIR is already installed and if it is, where
  32. ;is it located?  It works by adding another function to int 16h.  To use it
  33. ;ax = 7788h, bx = 7789h, and ds:si points to the signature string.  If any one
  34. ;of these conditions is not true, then the int 16h call is passed onto the
  35. ;old routine without doing anything.  If they are all true, then we switch
  36. ;ax and bx and return ds = code segment (cs) of the interrupt handler.
  37.  
  38. myint16    proc    far
  39.  
  40.     pushf                ;save flags
  41.     cmp    ax,7788h            ;possible signature request ?
  42.     je    CHECKSIG            ;yes
  43. NOTSIG:
  44.     popf                ;no - recover flags
  45.     jmp    cs:[savedint16]        ;go to old routine as normal
  46.  
  47. CHECKSIG:
  48.     cmp    bx,7789h        ;possible signature request ?
  49.     jne    NOTSIG            ;no
  50.  
  51.     ;ax and bx were correct for a signature request
  52.     ;now see if ds:si was pointing to the signature string
  53.     ;the whole idea of the signature is that is has to be
  54.     ;totally unique so no other program could possibly use the same one.
  55.  
  56.     push    es            ;save the registers we will use
  57.     push    di
  58.     push    cx 
  59.     mov    di,offset main:signature    ;address of the signature
  60.     mov    cx,lengthsignature        ;length of the signature
  61.     repe    cmpsb            ;does string at ds:si match es:di ?
  62.     pop    cx            ;recover all registers we used
  63.     pop    di
  64.     pop    es
  65.     jne    NOTSIG            ;no, not correct signature
  66.  
  67. ;yes, it was a signature request so return ds equal to the current code
  68. ;segment so subsequent pushdir's and popdir's know where the original
  69. ;is located.
  70.  
  71.     push    cs
  72.     pop    ds            ;set ds = cs
  73.     xchg    ax,bx            ;flip these two so we know that
  74.                     ;ds is being returned
  75.     popf                ;recover original flags
  76.     iret                ;return back to the program
  77.                     ;that called the int 16h
  78.  
  79. myint16    endp
  80.  
  81. endresident    label    byte        ;label marking the end of the
  82.                     ;code to remain resident
  83.  
  84. ;code after here will not remain resident
  85.  
  86. install        db    1    ;0 = already installed, 1 = not installed
  87.  
  88. abortmsg    db    'Error reading the current directory.$'
  89. installmsg    db    'PUSHDIR 1.a installed.$'
  90.  
  91. START:
  92.     sti                ;turn interrupts on
  93.  
  94.     ;first check to see if PUSHDIR is already installed
  95.  
  96.     mov    ax,7788h            ;signature request
  97.     mov    bx,7789h            ;signature request
  98.     mov    si,offset main:signature    ;point to signature
  99.     int    16h            ;is it installed ?
  100.     
  101. assume    ds:nothing
  102.     
  103.     cmp    bx,7788h            ;were ax and bx switched ?
  104.     jne    NOTINSTALLED        ;no
  105.     cmp    ax,7789h            ;were ax and bx switched ?
  106.     jne    NOTINSTALLED        ;no
  107.     
  108.     ;yes it is installed already
  109.  
  110.     mov    cs:[install],0        ;don't install it again
  111. NOTINSTALLED:
  112.     
  113.     ;ds = segment of the installation
  114.     
  115.     ;store the current directory, including disk drive letter
  116.     
  117.     mov    si,ds:[nextpush]    ;get storage address for next push
  118.     add    si,3            ;make room for d:\
  119.     mov    dl,0            ;default drive
  120.     mov    ah,47h            ;dos function number
  121.     int    21h            ;get current directory
  122.     jc    ABORTERR        ;error message if carry set
  123.     mov    ah,19h            ;dos function number
  124.     int    21h            ;get the current drive
  125.     add    al,'A'            ;convert to ascii
  126.     mov    byte ptr ds:[si-3],al    ;add the "D:\" in front of path
  127.     mov    byte ptr ds:[si-2],':'
  128.     mov    byte ptr ds:[si-1],'\'
  129.  
  130.     ;now update [nextpush] for the next PUSHDIR
  131.  
  132.     cmp    ds:[nextpush],offset main:push6dir    ;time to wrap around ?
  133.     je    WRAPPUSH                ;yes
  134.     add    ds:[nextpush],67            ;no, point to next one
  135.     jmp    short GOTNEXTPUSH 
  136. WRAPPUSH:
  137.     mov    ds:[nextpush],offset main:push1dir    ;wrap back to beginning
  138. GOTNEXTPUSH:
  139. ;-----------------------------------------------------------------------------
  140. ;
  141. ;    This block of code was added on 12/22/88 by Mike Williams
  142. ;    to support a command line parm to change directories
  143. ;    and (if necessary) select a new default drive.
  144. ;
  145. ;-----------------------------------------------------------------------------
  146.  
  147.         ;       look at psp command tail for directory parm
  148.         ;       and call change directory function
  149.  
  150.         push    ds
  151.         push    cs
  152.         pop     ds                    ;ensure ds is good
  153.         mov     bl,ds:[0080h]                   ;length of parm in psp
  154.                                                 ;command tail        
  155.         sub     bh,bh
  156.         add     bx,0081h                        ;add start addr to length
  157.         mov     byte ptr [bx],00h               ;string terminator
  158.         mov     si,0081h                        ;point to beginning of string
  159. CHDLOOP:                                        ;string is pointed to by ds:si
  160.         lodsb                                   ;look for first non-blank
  161.         cmp     al,20h                          ;blank?
  162.         je      CHDLOOP                         ;yes, try again
  163.         dec     si                              ;si got incremented in lodsb
  164.         mov     dx,si                           ;pointer to parm
  165.         mov     ah,3bh                          ;function call to CHDIR
  166.         int     21h                             ;DOS function call
  167.  
  168.     ;now check for the presence of a drive designator on the
  169.     ;path string and if present set the requested drive also    
  170.  
  171.         mov     bl,ds:[si+1]            ;pickup second char in parm
  172.         cmp     bl,':'                            ;is it a colon: ?
  173.         jne     AROUND                          ;no , go around this code
  174.                                                 ;yes
  175.     mov    dl,ds:[si]             ;get drive letter from path
  176.     and    dl,0dfh                ;convert to uppercase letter
  177.     sub    dl,'A'                ;convert to binary (0=A, 1=B)
  178.     mov    ah,0eh                ;dos function to select drive
  179.     int    21h                ;set drive
  180. AROUND:
  181.         pop     ds                              ;restore ds
  182.  
  183. ;--------------------------end of 12/22/88 change-----------------------------
  184.  
  185.     cmp    cs:[install],1            ;should we install it
  186.     je    DOINSTALL                ;yes
  187.     int    20h                ;no, we are done
  188.  
  189. ABORTERR:
  190.     mov    dx,offset main:abortmsg        ;address of error message
  191.     mov    ah,9                ;dos function number
  192.     int    21h                ;show error message
  193.     int    20h                ;end program on error
  194.  
  195.  
  196.     ;if we got to here, then pushdir is not already installed,
  197.     ;so we need to install it by making part of it memory resident.
  198.  
  199. DOINSTALL:
  200.     push    cs
  201.     pop    ds            ;set ds = cs
  202.  
  203. assume    ds:main
  204.  
  205.     ;save the current int 16h vector
  206.  
  207.     push    es            ;save es
  208.     mov    ax,3516h            ;dos function 35h, vector 16h
  209.     int    21h            ;get the existing vector into es:bx
  210.     mov    word ptr [savedint16],bx    ;save es:bx
  211.     mov    word ptr [savedint16+2],es    ;save es:bx
  212.     pop    es            ;recover es
  213.  
  214.     ;now set the new int 16h vector to point to my routine
  215.  
  216.     mov    dx,offset main:myint16    ;point to my new routine
  217.     mov    ax,2516h            ;dos function 25h, vector 16h
  218.     int    21h            ;set new vector to ds:dx
  219.  
  220.     ;now show a message on the screen
  221.     ;this message can be suppressed by redirecting output to NUL
  222.     ;by using pushdir like this: PUSHDIR >NUL
  223.  
  224.     mov    dx,offset main:installmsg
  225.     mov    ah,9
  226.     int    21h            ;show installation message
  227.  
  228.     ;now free up the memory occupied by the envirnoment so it is not
  229.     ;permanently wasted
  230.  
  231.     mov    ax,ds:[2ch]        ;get segment of environment
  232.     mov    es,ax            ;load envirnoment segment into es
  233.     mov    ah,49h            ;dos function number
  234.     int    21h            ;free the environment memory
  235.  
  236.     ;now terminate resident protecting only the first part of this program
  237.  
  238.     mov    dx,offset main:endresident    ;point to end of resident code
  239.     add    dx,0fh            ;round up
  240.     mov    cl,4
  241.     shr    dx,cl